package common.util;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.Pipeline;
import com.itextpdf.tool.xml.XMLWorker;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import com.itextpdf.tool.xml.html.CssAppliersImpl;
import com.itextpdf.tool.xml.html.Tags;
import com.itextpdf.tool.xml.net.FileRetrieve;
import com.itextpdf.tool.xml.net.ReadingProcessor;
import com.itextpdf.tool.xml.parser.XMLParser;
import com.itextpdf.tool.xml.pipeline.css.CSSResolver;
import com.itextpdf.tool.xml.pipeline.css.CssResolverPipeline;
import com.itextpdf.tool.xml.pipeline.end.PdfWriterPipeline;
import com.itextpdf.tool.xml.pipeline.html.*;
import org.apache.commons.lang3.StringUtils;
import org.xhtmlrenderer.pdf.ITextRenderer;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.net.URLDecoder;
import java.nio.charset.Charset;

public class PdfGenerator {
    
    /**
     * @Author: nxs@winning.com.cn
     *
     * @Description: 输出PDF文件到指定的输出流 
     *
     * @Date:  2018-04-11 17:31:13
     *
     * @Param: [htmlStr, out]
     *
     * @return: void
     *
     **/
    public static void generate(String htmlStr, OutputStream out)
            throws Exception {
        DocumentBuilder builder = DocumentBuilderFactory.newInstance()
                .newDocumentBuilder();
        org.w3c.dom.Document doc = builder.parse(new ByteArrayInputStream(htmlStr
                .getBytes()));
        ITextRenderer renderer = new ITextRenderer();
        renderer.setDocument(doc, null);
        renderer.layout();
        renderer.createPDF(out);
        out.close();
    }
    /**
     * @Author: nxs@winning.com.cn
     *
     * @Description: 解析并输出到客户端
     *
     * @Date:  2018-04-13 17:38:27
     *
     * @Param: [htmlStr, out]
     *
     * @return: void
     *
     **/
    public  void generatePlus(String htmlStr, OutputStream out) throws IOException, DocumentException {
        final String charsetName = "UTF-8";

        Document document = new Document(PageSize.A4, 30, 30, 30, 30);
        document.setMargins(30, 30, 30, 30);
        PdfWriter writer = PdfWriter.getInstance(document, out);
        document.open();


        // html内容解析
        HtmlPipelineContext htmlContext = new HtmlPipelineContext(
                new CssAppliersImpl(new XMLWorkerFontProvider() {
                    @Override
                    public Font getFont(String fontname, String encoding,
                                        float size, final int style) {
                        Font font = null;
                        if (fontname == null) {
                            //字体
                            String fontCn = getChineseFont();
                            BaseFont bf;
                            try {
                                //注意这里有一个,1
                                bf = BaseFont.createFont(fontCn+",1",
                                        BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
                                font = new Font(bf, size, style);
                            } catch (DocumentException e) {
                                e.printStackTrace();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }

                        }
                        return font;
                    }
                })) {
            @Override
            public HtmlPipelineContext clone()
                    throws CloneNotSupportedException {
                HtmlPipelineContext context = super.clone();
                try {
                    ImageProvider imageProvider = this.getImageProvider();
                    context.setImageProvider(imageProvider);
                } catch (NoImageProviderException e) {
                }
                return context;
            }
        };

        // 图片解析
        htmlContext.setImageProvider(new AbstractImageProvider() {

            String rootPath = PdfGenerator.class.getResource("/").getPath();

            @Override
            public String getImageRootPath() {
                return rootPath;
            }

            @Override
            public Image retrieve(String src) {
                if (StringUtils.isEmpty(src)) {
                    return null;
                }
                try {
                    Image image = Image.getInstance(new File(rootPath, src).toURI().toString());
                    // 图片显示位置
                    image.setAbsolutePosition(400, 400);
                    if (image != null) {
                        store(src, image);
                        return image;
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                }
                return super.retrieve(src);
            }
        });
        htmlContext.setAcceptUnknown(true).autoBookmark(true).setTagFactory(Tags.getHtmlTagProcessorFactory());

        // css解析
        CSSResolver cssResolver = XMLWorkerHelper.getInstance().getDefaultCssResolver(true);
        cssResolver.setFileRetrieve(new FileRetrieve() {
            @Override
            public void processFromStream(InputStream in,
                                          ReadingProcessor processor) throws IOException {
                try {
                    InputStreamReader reader = new InputStreamReader(in, charsetName);
                    int i = -1;
                    while (-1 != (i = reader.read())) {
                        processor.process(i);
                    }
                } catch (Throwable e) {
                }
            }

            // 解析href
            @Override
            public void processFromHref(String href, ReadingProcessor processor) throws IOException {
                InputStream is = PdfGenerator.class.getResourceAsStream("/" + href);
                try {
                    InputStreamReader reader = new InputStreamReader(is,charsetName);

                    int i = -1;
                    while (-1 != (i = reader.read())) {
                        processor.process(i);
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        });

        HtmlPipeline htmlPipeline = new HtmlPipeline(htmlContext, new PdfWriterPipeline(document, writer));
        Pipeline<?> pipeline = new CssResolverPipeline(cssResolver, htmlPipeline);
        XMLWorker worker = null;
        worker = new XMLWorker(pipeline, true);
        XMLParser parser = new XMLParser(true, worker, Charset.forName(charsetName));
        try {
            InputStream inputStream = new ByteArrayInputStream(htmlStr.getBytes());

            //parser.parse(inputStream, Charset.forName("GB2312"));
            parser.parse(inputStream, Charset.defaultCharset());
        }catch (Exception e)
        {
            e.printStackTrace();
        }
        document.close();
    }

    /**
     * @Author: nxs@winning.com.cn
     *
     * @Description: 获取中文字体位置
     *
     * @Date:  2018-04-11 17:33:01
     *
     * @Param: []
     *
     * @return: java.lang.String
     *
     **/
    private  String getChineseFont() {
        String chineseFont = null;
        try {
            String str=this.getClass().getResource("/").getPath();
            chineseFont = URLDecoder.decode(this.getClass().getResource("/").getPath() + "template/SIMSUN.TTC","UTF-8");

           /* Map<String, Object> variables = new HashMap<String, Object>();
            chineseFont =  HtmlGenerator.generate("SIMSUN.TTC", variables);*/
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(!new File(chineseFont).exists()){
            throw new RuntimeException("字体文件不存在,影响导出pdf中文显示！"+chineseFont);
        }

        return chineseFont;
    }
}
